package middleware

import (
	"regexp"
	"strings"
	"supershare/backend/models"

	"github.com/beego/beego/v2/server/web"
	"github.com/beego/beego/v2/server/web/context"
)

// CheckPermission 检查用户是否拥有指定权限
func CheckPermission() web.FilterFunc {
	return func(ctx *context.Context) {
		if ctx.ResponseWriter.Status >= 400 {
			return // 如果认证中间件已经设置了错误状态，直接返回
		}

		// 白名单路径，不需要权限检查
		whiteList := []string{
			"/api/auth/login",
			"/api/user/info",
		}

		// 检查是否在白名单中
		path := ctx.Request.URL.Path
		for _, whitePath := range whiteList {
			if path == whitePath {
				return
			}
		}

		// 从上下文中获取用户ID
		userId, ok := ctx.Input.GetData("user_id").(int64)
		if !ok {
			// 用户未登录或ID无效
			ctx.Output.Status = 401
			ctx.Output.JSON(map[string]interface{}{
				"success": false,
				"message": "未授权访问",
			}, false, false)
			return
		}

		// 获取用户权限
		permissions, err := models.GetAdminPermissions(userId)
		if err != nil {
			ctx.Output.Status = 500
			ctx.Output.JSON(map[string]interface{}{
				"success": false,
				"message": "获取权限失败",
			}, false, false)
			return
		}

		method := ctx.Request.Method
		hasPermission := false

		// 检查是否有权限
		for _, permission := range permissions {
			// 跳过非API类型的权限
			if permission.Type != "api" {
				continue
			}

			// 将权限资源路径中的参数占位符转换为正则表达式模式
			// 例如: /api/v1/role/:id -> /api/v1/role/(.+)
			patternStr := strings.ReplaceAll(permission.Identifier, ":id", "([^/]+)")

			// 处理其他可能的参数占位符，如:name, :type等
			re := regexp.MustCompile(":[a-zA-Z0-9_]+")
			patternStr = re.ReplaceAllString(patternStr, "([^/]+)")

			// 编译正则表达式
			pattern := regexp.MustCompile("^" + patternStr + "$")

			// 检查请求路径是否匹配模式，以及请求方法是否允许
			if pattern.MatchString(path) && (permission.Method == "*" || permission.Method == method) {
				hasPermission = true
				break
			}
		}

		// 如果没有权限，返回403
		if !hasPermission {
			ctx.Output.Status = 403
			ctx.Output.JSON(map[string]interface{}{
				"success": false,
				"message": "没有操作权限",
			}, false, false)
			return
		}

		// 处理接口操作日志
		LogMiddleware(ctx)
	}
}

// GetCurrentAdmin 获取当前登录的管理员信息
func GetCurrentAdmin(ctx *context.Context) (*models.Admin, error) {
	// 从上下文中获取用户ID
	userId, ok := ctx.Input.GetData("user_id").(int64)
	if !ok {
		return nil, nil
	}

	// 获取管理员信息
	return models.GetAdminById(userId)
}
